﻿

using IotClientService.Enums;
using SyncSocketModuleCore.SyncSocketModule;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace IotClientService.Handles;
/// <summary>
/// 西门子S7 tt 处理器
/// </summary>
public class SiemensS7PacketHandler : IPacketHandler
{
    public SiemensS7PacketHandler()
    {
    }

    public bool BatchReadPacket(int _ReadStartWordAddr, int _ReadWordCount, int _DeviceCode, out int _ReadCmdAckPacketSize, out byte[] _ReadCmdPacket, out string _ErrorText, int DBBlock = 0)
    {
        _ReadCmdPacket = null;
        _ReadCmdAckPacketSize = 0;
        try
        {
            _ReadCmdAckPacketSize = 21 + _ReadWordCount * 2;
            MemoryStream ms = new MemoryStream(_ReadCmdAckPacketSize);
            int amount = 1;
            ms.WriteByte(3);
            ms.WriteByte(0);
            byte[] Items = IntToByteArray((short)(19 + 12 * amount));
            ms.Write(Items, 0, Items.Length);
            ms.WriteByte(2);
            ms.WriteByte(240);
            ms.WriteByte(128);
            ms.WriteByte(50);
            ms.WriteByte(1);
            ms.WriteByte(0);
            ms.WriteByte(0);
            ms.WriteByte(0);
            ms.WriteByte(0);
            Items = WordToByteArray((ushort)(2 + amount * 12));
            ms.Write(Items, 0, Items.Length);
            ms.WriteByte(0);
            ms.WriteByte(0);
            ms.WriteByte(4);
            ms.WriteByte(1);
            ms.WriteByte(18);
            ms.WriteByte(10);
            ms.WriteByte(16);
            ms.WriteByte(2);
            Items = WordToByteArray((ushort)(_ReadWordCount * 2));
            ms.Write(Items, 0, Items.Length);
            Items = WordToByteArray((ushort)DBBlock);
            ms.Write(Items, 0, Items.Length);
            ms.WriteByte(132);
            int overflow = (int)((long)(_ReadStartWordAddr * 2 * 8) / 65535L);
            ms.WriteByte((byte)overflow);
            Items = WordToByteArray((ushort)(_ReadStartWordAddr * 2 * 8));
            ms.Write(Items, 0, Items.Length);
            _ReadCmdPacket = ms.ToArray();
            _ErrorText = "";
            if (_ReadWordCount < 1 || _ReadWordCount > 438)
            {
                _ErrorText = "Plc Read Word Count Error";
                return false;
            }
        }
        catch (Exception _ex)
        {
            _ErrorText = $"Exception : {_ex.Message}\r\n{_ex.Source}\r\n{_ex.StackTrace}";
            return false;
        }
        return true;
    }

    public bool BatchReadResponse(byte[] _RecvedByte, int _RecvedByteCount, int _RespectRecvByteCunt, int _AccessWordCount, ref byte[] _CopyTarget, out string _ErrorText)
    {
        
        StringBuilder stringBuilder = new StringBuilder();
        _ErrorText = "NoError";
        bool flag = true;
        if (_RecvedByteCount < 15)
        {
            flag = false;
            stringBuilder.Append(" Packet Header Size  : ");
            int length = (int)_RecvedByte.Length;
            stringBuilder.Append(length.ToString());
            _ErrorText = stringBuilder.ToString();
            return flag;
        }
        ReadWriteErrorCode readWriteErrorCode = (ReadWriteErrorCode)_RecvedByte[17];
        switch (readWriteErrorCode)
        {
            case ReadWriteErrorCode.HardwareFault:
                {
                    _ErrorText = "Received error from PLC: Hardware fault.";
                    break;
                }
            case ReadWriteErrorCode.AccessingObjectNotAllowed:
                {
                    _ErrorText = "Received error from PLC: Accessing object not allowed.";
                    break;
                }
            case ReadWriteErrorCode.AddressOutOfRange:
                {
                    _ErrorText = "Received error from PLC: Address out of range.";
                    break;
                }
            case ReadWriteErrorCode.DataTypeNotSupported:
                {
                    _ErrorText = "Received error from PLC: Data type not supported.";
                    break;
                }
            case ReadWriteErrorCode.DataTypeInconsistent:
                {
                    _ErrorText = "Received error from PLC: Data type inconsistent.";
                    break;
                }
            case ReadWriteErrorCode.ObjectDoesNotExist:
                {
                    _ErrorText = "Received error from PLC: Object does not exist.";
                    break;
                }
            default:
                {
                    if (readWriteErrorCode == ReadWriteErrorCode.Success)
                    {
                        break;
                    }
                    _ErrorText = "Invalid response from PLC: statusCode={(byte)statusCode}.";
                    break;

                }
        }
        if (_RecvedByte[17] != 255)
        {
            stringBuilder.Append(_ErrorText);
            return false;
        }
        if ((int)_RecvedByte.Length < _RespectRecvByteCunt + 18 + 4)
        {
            flag = false;
            stringBuilder.Append(" Packet Size  : ");
            int num = (int)_RecvedByte.Length;
            stringBuilder.Append(num.ToString());
            _ErrorText = stringBuilder.ToString();
            return flag;
        }
        if (flag)
        {
            for (int i = 0; i < (_RecvedByteCount - 21) / 2; i++)
            {
                _CopyTarget[i * 2] = _RecvedByte[21 + i * 2 + 1];
                _CopyTarget[i * 2 + 1] = _RecvedByte[21 + i * 2];
            }
        }
        _ErrorText = stringBuilder.ToString();
        return flag;
    }

    public bool BatchWritePacket(int[] _WriteWordData, int _WriteStartWordAddr, int _WriteWordCount, int _DeviceCode, out int _WriteCmdAckPacketSize, out byte[] _WriteCmdPacket, out string _ErrorText, int DBBlock = 0)
    {
        try
        {
            _WriteStartWordAddr *= 2;
            byte[] value = new byte[_WriteWordData.Length * 2];
            for (int i = 0; i < _WriteWordData.Length; i++)
            {
                value[i * 2] = (byte)((_WriteWordData[i] & 0xFF00) >> 8);
                value[i * 2 + 1] = (byte)((uint)_WriteWordData[i] & 0xFFu);
            }
            int _WriteByteCount = _WriteWordCount * 2;
            _WriteCmdAckPacketSize = 35 + _WriteByteCount;
            MemoryStream ms = new MemoryStream(_WriteCmdAckPacketSize);
            ms.WriteByte(3);
            ms.WriteByte(0);
            byte[] Items = IntToByteArray((short)_WriteCmdAckPacketSize);
            ms.Write(Items, 0, Items.Length);
            ms.WriteByte(2);
            ms.WriteByte(240);
            ms.WriteByte(128);
            ms.WriteByte(50);
            ms.WriteByte(1);
            ms.WriteByte(0);
            ms.WriteByte(0);
            Items = WordToByteArray((ushort)(_WriteByteCount - 1));
            ms.Write(Items, 0, Items.Length);
            ms.WriteByte(0);
            ms.WriteByte(14);
            Items = WordToByteArray((ushort)(_WriteByteCount + 4));
            ms.Write(Items, 0, Items.Length);
            ms.WriteByte(5);
            ms.WriteByte(1);
            ms.WriteByte(18);
            ms.WriteByte(10);
            ms.WriteByte(16);
            ms.WriteByte(2);
            Items = WordToByteArray((ushort)_WriteByteCount);
            ms.Write(Items, 0, Items.Length);
            Items = WordToByteArray((ushort)DBBlock);
            ms.Write(Items, 0, Items.Length);
            ms.WriteByte(132);
            int overflow = (int)((long)(_WriteStartWordAddr * 8) / 65535L);
            ms.WriteByte((byte)overflow);
            Items = WordToByteArray((ushort)(_WriteStartWordAddr * 8));
            ms.Write(Items, 0, Items.Length);
            ms.WriteByte(0);
            ms.WriteByte(4);
            Items = WordToByteArray((ushort)(_WriteByteCount * 8));
            ms.Write(Items, 0, Items.Length);
            ms.Write(value, 0, _WriteByteCount);
            _WriteCmdPacket = ms.ToArray();
            _ErrorText = "";
        }
        catch (Exception _ex)
        {
            _ErrorText = $"Exception : {_ex.Message}\r\n{_ex.Source}\r\n{_ex.StackTrace}";
            _WriteCmdPacket = null;
            _WriteCmdAckPacketSize = 0;
            return false;
        }
        return true;
    }

    public bool BatchWriteResponse(byte[] _RecvedByte, int _RecvedByteCount, int _RespectRecvByteCunt, int _AccessWordCount, out string _ErrorText)
    {
        StringBuilder stringBuilder = new StringBuilder();
        bool flag = true;
        if ((int)_RecvedByte.Length >= 11)
        {
            _ErrorText = stringBuilder.ToString();
            return flag;
        }
        flag = false;
        stringBuilder.Append(" Packet Header Size  : ");
        int length = (int)_RecvedByte.Length;
        stringBuilder.Append(length.ToString());
        _ErrorText = stringBuilder.ToString();
        return flag;
    }

    public int GetPlcDataLength()
    {
        return 438;
    }

    public static byte[] IntToByteArray(short value)
    {
        byte[] numArray = new byte[] { (byte)(value >> 8 & 255), (byte)(value & 255) };
        return numArray;
    }

    public bool IsNeedNodeSync()
    {
        return false;
    }

    public bool IsReqeustSync()
    {
        return false;
    }

    public bool ReadNodeAddress(out byte[] _ReadCmdPacket, out string _ErrorText)
    {
        _ReadCmdPacket = null;
        _ErrorText = null;
        return false;
    }

    public bool ReadNodeResponse(byte[] _RecvedByte, int _RecvedByteCount, int _RespectRecvByteCunt, int _AccessWordCount, out string _ErrorText)
    {
        _ErrorText = null;
        return false;
    }

    public byte[] WordToByteArray(ushort value)
    {
        byte[] numArray = new byte[] { 0, (byte)(value & 255) };
        numArray[0] = (byte)(value >> 8 & 255);
        return numArray;
    }
}
